﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml.Schema;

namespace ExpressionTreeLib
{
    class MethodConverter : TypeConverter
    {
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            var method = context.PropertyDescriptor.GetValue(context.Instance) as Method;
            if (method == null || method.MethodInfo == null)
                return new StandardValuesCollection(new object[0]);

            var methodDeclareType = method.MethodInfo.DeclaringType;

            return new StandardValuesCollection(methodDeclareType.GetMethods().ToArray());
        }

        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType.Equals(typeof(string)) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            //System.String Join(System.String, System.Object[])
            var fullMethod = value.ToString();
            var methodName = fullMethod.Split(' ')[1].Split('(')[0];
            var methodDeclareType = (context.PropertyDescriptor.GetValue(context.Instance) as Method).MethodInfo.DeclaringType;

            var types = new List<Type>();
            foreach (var parameterType in fullMethod.Split('(')[1].Split(')')[0].Split(new string[]{ ", "}, StringSplitOptions.RemoveEmptyEntries))
            {
                var type = Type.GetType(parameterType) ?? Type.GetType("System." + parameterType);//Char[] => System.Char[]
                types.Add(type);
            }

            var method = methodDeclareType.GetMethod(methodName, types.ToArray());

            return new Method{ MethodInfo = method };
        }
    }

    [TypeConverter(typeof(MethodConverter))]
    public class Method
    {
        public MethodInfo MethodInfo { get; set; }
        public override string ToString()
        {
            return MethodInfo.ToString();
        }
    }
}
